import React, { useCallback, useMemo } from 'react'
import {
  Button as AntdButton,
  ButtonProps as AntdButtonProps,
  Popconfirm,
} from 'antd'
import { FormattedMessage } from '@designable/event-system'
import createEvent, { useT, CreateExecutor } from '@designable/event-system'
import { useForm } from '@formily/react'
import { useDialogInstances } from '@designable/react'
import AccessBox from '../AccessBox'
import * as AntdIcons from '@ant-design/icons'

type ButtonType = 'default' | 'link' | 'text' | 'ghost' | 'primary' | 'dashed'

export interface I18nButtonProps extends AntdButtonProps {
  onClick?: (e: React.MouseEvent) => void
  children?: React.ReactNode
  /** 点击时执行的表达式 */
  onClickExpression?: string
  /** 按钮文本 */
  text: string
  /** 按钮类型 */
  type?: ButtonType
  /** 禁用状态表达式 */
  disabled?: any
  /** 对话框标识符 */
  dialog?: string
  /** 可见性控制表达式 */
  visible?: any
  /** 权限标识符 */
  accessKey?: string
  /** 是否使用确认弹窗 */
  usePopconfirm?: boolean
  /** 确认弹窗标题 */
  popconfirmTitle?: string
  /** 按钮尺寸 */
  size?: 'large' | 'middle' | 'small'
  /** 图标名称 */
  icon?: string
  /** 自定义表达式 */
  customExpression?: any
  /** 按钮类型（与type重复，保持兼容性） */
  buttonType?: ButtonType
}

// 工具函数
const safeExecute = (executor: any, context: any, fallback: any = null) => {
  try {
    return CreateExecutor(executor)(context)
  } catch (error) {
    console.error('执行表达式失败:', error)
    return fallback
  }
}

const getIconComponent = (iconName: string) => {
  return iconName && (AntdIcons as Record<string, any>)[iconName]
}

export const Button: React.FC<I18nButtonProps> = (props) => {
  const form = useForm()
  const $t = useT()
  const dialogInstances = useDialogInstances()

  const {
    children,
    onClickExpression,
    onClick,
    accessKey,
    text,
    type,
    buttonType,
    disabled,
    dialog,
    visible,
    usePopconfirm,
    popconfirmTitle,
    size,
    icon,
    customExpression,
    ...rest
  } = props

  // 检查可见性
  const isVisible = useMemo(() => {
    if (!visible) return true
    return safeExecute(visible, { form, $t }, true)
  }, [visible, form, $t])

  // 检查禁用状态
  const isDisabled = useMemo(() => {
    if (!disabled) return false
    return safeExecute(disabled, { form, $t }, false)
  }, [disabled, form, $t])

  // 如果不可见，直接返回null
  if (!isVisible) {
    return null
  }

  const content = useMemo(() => {
    if (children) {
      return typeof children === 'string' ? (
        <FormattedMessage id={children} />
      ) : (
        children
      )
    }
    return $t(text)
  }, [children, text, $t])

  // 获取图标组件
  const IconComponent = useMemo(() => {
    return getIconComponent(icon)
  }, [icon])

  // 执行表达式
  const exec = useCallback(
    async (expression?: string, event?: React.MouseEvent) => {
      if (!expression) return
      try {
        await createEvent(expression as string, {
          form,
          event,
          $t,
        })
      } catch (e) {
        console.error('执行表达式失败:', e)
      }
    },
    [form, $t]
  )

  // 处理按钮点击事件
  const handleClick = useCallback(
    async (e: React.MouseEvent) => {
      // 执行自定义表达式
      if (customExpression) {
        await createEvent(customExpression, { form, event: e, $t })
      }

      // 执行点击表达式
      if (onClickExpression) {
        await exec(onClickExpression, e)
      }

      // 打开对话框
      if (dialog) {
        const dialogInstance = dialogInstances.get(dialog)
        if (dialogInstance) {
          ;(dialogInstance as any).open({
            form,
            event: e,
            $t,
          })
        }
      }

      // 执行原始onClick
      onClick?.(e as any)
    },
    [
      customExpression,
      onClickExpression,
      dialog,
      form,
      $t,
      exec,
      onClick,
      dialogInstances,
    ]
  )

  // 按钮属性
  const buttonProps = useMemo(
    () => ({
      ...rest,
      type: buttonType || type || 'default',
      size,
      disabled: isDisabled,
      icon: IconComponent ? <IconComponent /> : undefined,
    }),
    [rest, buttonType, type, size, isDisabled, IconComponent]
  )

  const buttonElement = (
    <AccessBox accessKey={accessKey}>
      <AntdButton
        {...buttonProps}
        onClick={usePopconfirm ? undefined : handleClick}
      >
        {content}
      </AntdButton>
    </AccessBox>
  )

  // 如果需要确认弹窗
  if (usePopconfirm) {
    return (
      <Popconfirm
        title={
          popconfirmTitle ? $t(popconfirmTitle) : $t('确定要执行该操作吗？')
        }
        onConfirm={handleClick}
      >
        <span>{buttonElement}</span>
      </Popconfirm>
    )
  }

  return buttonElement
}

// 使用 observer 包装组件以支持响应式更新
export default Button
